package com.nononsenseapps.feeder.ui.home

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import com.nononsenseapps.feeder.db.entity.ATTENTION_NORMAL
import com.nononsenseapps.feeder.ui.R
import com.nononsenseapps.feeder.model.FeedUnreadCount
import java.util.*

private const val VIEWTYPE_ALL = 0
private const val VIEWTYPE_TAG = 1
private const val VIEWTYPE_FEED = 2
private const val VIEWTYPE_FEED_CHILD = 3
private const val VIEWTYPE_FAVORITE = 4
private const val VIEWTYPE_RULE = 5
private const val VIEWTYPE_HOT = 6
private const val VIEWTYPE_RECYCLE = 7
private const val VIEWTYPE_STORE = 8
private const val VIEWTYPE_MEMO = 9
private const val VIEWTYPE_BACKUP = 10
private const val VIEWTYPE_READ_LATE= 11

class FeedsAdapter(private val onClickListener: OnNavigationItemClickListener) : androidx.recyclerview.widget.RecyclerView.Adapter<androidx.recyclerview.widget.RecyclerView.ViewHolder>() {
    private val expandedTags: MutableSet<String> = androidx.collection.ArraySet(setOf(""))
    private var allItems: List<FeedUnreadCount> = emptyList()
    private var visibleItems: List<FeedUnreadCount> = emptyList()

    init {
        setHasStableIds(true)
    }

    private var context:Context?=null

    override fun getItemCount(): Int = visibleItems.size

    override fun getItemId(position: Int): Long {
        val item = visibleItems[position]
        return if (item.isAllFeeds || !item.isTag || item.isSystemFeed) {
            item.id
        } else {
            item.tag.hashCode().toLong()
        }
    }

    override fun getItemViewType(position: Int): Int {
        val item = visibleItems[position]
        return when {
            item.isAllFeeds -> VIEWTYPE_ALL
            item.isFavorite-> VIEWTYPE_FAVORITE
            item.isReadLate-> VIEWTYPE_READ_LATE
            item.isHot-> VIEWTYPE_HOT
            item.isRecycle-> VIEWTYPE_RECYCLE
            item.isRule-> VIEWTYPE_RULE
            item.isStore-> VIEWTYPE_STORE
            item.isMemo -> VIEWTYPE_MEMO
            item.isTag -> VIEWTYPE_TAG
            item.isBackup -> VIEWTYPE_BACKUP
            item.tag.isEmpty() -> VIEWTYPE_FEED
            else -> VIEWTYPE_FEED_CHILD
        }
    }

    fun submitList(items: List<FeedUnreadCount>) {
        allItems = items
        updateView()
    }

    private fun updateView() {
        val oldVisibleItems = visibleItems
        visibleItems = allItems.filter {
            when {
                it.isAllFeeds -> true
                it.isSystemFeed->true
                it.isTag -> expandedTags.contains("")
                expandedTags.contains(it.tag) -> true
                else -> it.attentionLevel > ATTENTION_NORMAL && it.unreadCount>0
            }
        }

        val diffResult = DiffUtil.calculateDiff(object: DiffUtil.Callback() {
            override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
                val oldItem: FeedUnreadCount = oldVisibleItems[oldItemPosition]
                val newItem: FeedUnreadCount = visibleItems[newItemPosition]

                return when {
                    oldItem.isTag && newItem.isTag -> oldItem.tag == newItem.tag
                    !oldItem.isTag && !newItem.isTag -> oldItem.id == newItem.id
                    else -> false
                }
            }

            override fun getOldListSize(): Int = oldVisibleItems.size

            override fun getNewListSize(): Int = visibleItems.size

            override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
                val oldItem: FeedUnreadCount = oldVisibleItems[oldItemPosition]
                val newItem: FeedUnreadCount = visibleItems[newItemPosition]

                return when {
                    oldItem.isTag && newItem.isTag -> {
                                oldItem.unreadCount == newItem.unreadCount
                    }
                    !oldItem.isTag && !newItem.isTag -> {
                        oldItem.displayTitle == newItem.displayTitle &&
                                oldItem.unreadCount == newItem.unreadCount
                    }
                    else -> false
                }
            }
        })

        diffResult.dispatchUpdatesTo(this)
    }

    /**
     * true if tag is expanded after this call, false otherwise
     */
    fun toggleExpansion(item: FeedUnreadCount): Boolean {
        val result = if (expandedTags.contains(item.tag)) {
            expandedTags.remove(item.tag)
            false
        } else {
            expandedTags.add(item.tag)
            true
        }
        updateView()
        return result
    }

    private fun isExpanded(item: FeedUnreadCount): Boolean {
        return expandedTags.contains(item.tag)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): androidx.recyclerview.widget.RecyclerView.ViewHolder {
        context=parent.context
        return when (viewType) {
            VIEWTYPE_FEED_CHILD -> FeedHolder(onClickListener, LayoutInflater.from(parent.context).inflate(R.layout.view_feed_child, parent, false))
            VIEWTYPE_TAG -> TagHolder(onClickListener, this, LayoutInflater.from(parent.context).inflate(R.layout.view_feed_tag, parent, false))
            VIEWTYPE_ALL -> AllFeedHolder(onClickListener, LayoutInflater.from(parent.context).inflate(R.layout.view_feed, parent, false))
            VIEWTYPE_FAVORITE ->FavoriteHolder(onClickListener, LayoutInflater.from(parent.context).inflate(R.layout.view_feed, parent, false))
            VIEWTYPE_READ_LATE ->ReadLateHolder(onClickListener, LayoutInflater.from(parent.context).inflate(R.layout.view_feed, parent, false))
            VIEWTYPE_HOT->HotHolder(onClickListener, LayoutInflater.from(parent.context).inflate(R.layout.view_feed, parent, false))
            VIEWTYPE_RULE->RuleHolder(onClickListener, LayoutInflater.from(parent.context).inflate(R.layout.view_feed, parent, false))
            VIEWTYPE_RECYCLE->RecycleHolder(onClickListener, LayoutInflater.from(parent.context).inflate(R.layout.view_feed, parent, false))
            VIEWTYPE_STORE->StoreHolder(onClickListener, LayoutInflater.from(parent.context).inflate(R.layout.view_feed, parent, false))
            VIEWTYPE_MEMO->MemoHolder(onClickListener, LayoutInflater.from(parent.context).inflate(R.layout.view_feed, parent, false))
            VIEWTYPE_BACKUP->BackupHolder(onClickListener, LayoutInflater.from(parent.context).inflate(R.layout.view_feed, parent, false))
            // VIEWTYPE_FEED
            else -> FeedHolder(onClickListener, LayoutInflater.from(parent.context).inflate(R.layout.view_feed, parent, false))
        }
    }

    override fun onBindViewHolder(holder: androidx.recyclerview.widget.RecyclerView.ViewHolder, position: Int) {
        val wrap = visibleItems[position]
        when (getItemViewType(position)) {
            VIEWTYPE_FEED, VIEWTYPE_FEED_CHILD -> {
                val fh = holder as FeedHolder
                fh.item = wrap
                fh.title.text = wrap.displayTitle
                var text=if(wrap.unreadCount > 0) "${wrap.unreadCount}" else ""
                var unreadCountVisable = false
                    if(!wrap.syncAble){
                        text= "$text.P"
                        unreadCountVisable = true
                    }
                    if(!wrap.syncSuccess){
                        text= "$text.E"
                        unreadCountVisable = true
                    }
                    if(wrap.ruleAble){
                        text= "$text.F"
                        unreadCountVisable = true
                    }
                    if(wrap.unreadCount>0) unreadCountVisable = true
                fh.unreadCount.text = text
                fh.unreadCount.visibility =if(unreadCountVisable) View.VISIBLE else View.INVISIBLE
                context?.let {fh.showThumb(it)}
            }
            VIEWTYPE_TAG -> {
                val th = holder as TagHolder
                th.wrap = wrap
                th.title.text = wrap.tag
                if (isExpanded(wrap)) {
                    th.expander.setImageResource(R.drawable.tinted_expand_less)
                } else {
                    th.expander.setImageResource(R.drawable.tinted_expand_more)
                }
                th.unreadCount.text = "${wrap.unreadCount}"
                th.unreadCount.visibility = if (wrap.unreadCount > 0) View.VISIBLE else View.INVISIBLE
            }
            VIEWTYPE_ALL -> {
                val tp = holder as AllFeedHolder
                tp.unreadCount.text = "${wrap.unreadCount}"
                tp.unreadCount.visibility = if (wrap.unreadCount > 0) View.VISIBLE else View.INVISIBLE
            }
            VIEWTYPE_FAVORITE -> {
                val tp = holder as FavoriteHolder
                tp.item = wrap
                tp.title.text = wrap.displayTitle
                tp.unreadCount.text = "${wrap.unreadCount}"
                tp.unreadCount.visibility = if (wrap.unreadCount > 0) View.VISIBLE else View.INVISIBLE
            }
            VIEWTYPE_READ_LATE -> {
                val tp = holder as ReadLateHolder
                tp.item = wrap
                tp.title.text = wrap.displayTitle
                tp.unreadCount.text = "${wrap.unreadCount}"
                tp.unreadCount.visibility = if (wrap.unreadCount > 0) View.VISIBLE else View.INVISIBLE
            }
            VIEWTYPE_HOT -> {
                val tp = holder as HotHolder
                tp.item = wrap
                tp.title.text = wrap.displayTitle
                tp.unreadCount.text = "${wrap.unreadCount}"
                tp.unreadCount.visibility = if (wrap.unreadCount > 0) View.VISIBLE else View.INVISIBLE
            }
            VIEWTYPE_RULE -> {
                val tp = holder as RuleHolder
                tp.item = wrap
                tp.title.text = wrap.displayTitle
                tp.unreadCount.text = "${wrap.unreadCount}"
                tp.unreadCount.visibility = if (wrap.unreadCount > 0) View.VISIBLE else View.INVISIBLE
            }
            VIEWTYPE_RECYCLE -> {
                val tp = holder as RecycleHolder
                tp.item = wrap
                tp.title.text = wrap.displayTitle
                tp.unreadCount.text = "${wrap.unreadCount}"
                tp.unreadCount.visibility = if (wrap.unreadCount > 0) View.VISIBLE else View.INVISIBLE
            }
            VIEWTYPE_STORE -> {
                val tp = holder as StoreHolder
                tp.item = wrap
                tp.title.text = wrap.displayTitle
                tp.unreadCount.text = "${wrap.unreadCount}"
                tp.unreadCount.visibility = if (wrap.unreadCount > 0) View.VISIBLE else View.INVISIBLE
            }
            VIEWTYPE_MEMO -> {
                val tp = holder as MemoHolder
                tp.item = wrap
                tp.title.text = wrap.displayTitle
                tp.unreadCount.text = "${wrap.unreadCount}"
                tp.unreadCount.visibility = if (wrap.unreadCount > 0) View.VISIBLE else View.INVISIBLE
            }
            VIEWTYPE_BACKUP -> {
                val tp = holder as BackupHolder
                tp.item = wrap
                tp.title.text = wrap.displayTitle
                tp.unreadCount.text = "${wrap.unreadCount}"
                tp.unreadCount.visibility = if (wrap.unreadCount > 0) View.VISIBLE else View.INVISIBLE
            }
        }
    }
}

interface OnNavigationItemClickListener {
    fun onNavigationItemClick(id: Long, displayTitle: String?, url: String?, tag: String?)
    fun deleteFeed(id:Long)
    fun deleteFeedsInTag(tag: String)
    fun readAllWithFeedTag(tag: String,dateBefore: Date?=null)
    fun makeFeedAsRead(id: Long,dateBefore: Date?=null)
    fun syncFeedWithId(id: Long)
    fun syncFeedWithTag(tag: String)
    fun clearFeedItem(feedId: Long)
    fun moveFeedToFeed(frommFeedId: Long, toFeedId: Long)
    fun markAddFeedRule(id: Long)
    fun toggleFeedReadable(feedId: Long,readable: Boolean)
    fun toggleFeedWithTagReadable(tag: String,readable: Boolean)
    fun showFeedRule(feedId: Long)
    fun markFeedRuleAble(id: Long, ruleAble: Boolean)
    fun markFeedAttentionLevel(feedId: Long, attentionLevel: Int)
}
